{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "18868619",
   "metadata": {},
   "source": [
    "# 字典"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7eb51e8e",
   "metadata": {},
   "source": [
    "字典是一种由键值对组成的数据结构。\n",
    "\n",
    "顾名思义，我们把键想象成字典中的单词，值想象成词对应的定义，那么一个词可以对应一个或者多个定义，但是这些定义只能通过这个词来进行查询。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7ffed193",
   "metadata": {},
   "source": [
    "## 基本操作\n",
    "\n",
    "空字典可以使用`{}`或者`dict()`来创建一个空的字典："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "2141de1b",
   "metadata": {},
   "outputs": [],
   "source": [
    "a = {}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "ebaa4c6b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dict"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "99b9cdd5",
   "metadata": {},
   "outputs": [],
   "source": [
    "a = dict()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "d1df786f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dict"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1ca42ca2",
   "metadata": {},
   "source": [
    "有了dict之后，可以用索引键值的方法向其中添加元素，也可以通过索引来查看元素的值。\n",
    "\n",
    "插入键值："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "4e7cc92a",
   "metadata": {},
   "outputs": [],
   "source": [
    "a[\"one\"] = \"this is number 1\"\n",
    "a[\"two\"] = \"this is number 2\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "9960fe7d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'one': 'this is number 1', 'two': 'this is number 2'}"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ad68ff65",
   "metadata": {},
   "source": [
    "查看键值："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "1fbe660a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'this is number 1'"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a['one']"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a509370b",
   "metadata": {},
   "source": [
    "更新键值："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "e1681b26",
   "metadata": {},
   "outputs": [],
   "source": [
    "a[\"one\"] = \"this is number 1, too\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "7ba1a99c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'one': 'this is number 1, too', 'two': 'this is number 2'}"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9568657b",
   "metadata": {},
   "source": [
    "## 初始化字典\n",
    "\n",
    "可以看到，Python使用key: value这样的结构来表示字典中的元素结构，事实上，可以直接使用这样的结构来初始化一个字典："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "93d222dd",
   "metadata": {},
   "outputs": [],
   "source": [
    "b = {'one': 'this is number 1', 'two': 'this is number 2'}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "8eedadbd",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'this is number 1'"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b['one']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "fe3e0fc6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'one': 'this is number 1, too', 'two': 'this is number 2'}\n"
     ]
    }
   ],
   "source": [
    "print(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "78f19fd1",
   "metadata": {},
   "source": [
    "## 字典没有顺序"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bd480fa5",
   "metadata": {},
   "source": [
    "Python中不能用支持用数字索引按顺序查看字典中的值，而且数字本身也有可能成为键值，这样会引起混淆："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "41ebc129",
   "metadata": {},
   "outputs": [
    {
     "ename": "KeyError",
     "evalue": "0",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mKeyError\u001b[0m                                  Traceback (most recent call last)",
      "Input \u001b[0;32mIn [13]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43ma\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m]\u001b[49m\n",
      "\u001b[0;31mKeyError\u001b[0m: 0"
     ]
    }
   ],
   "source": [
    "a[0]"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "4c437774",
   "metadata": {},
   "source": [
    "## 键必须是不可变的类型\n",
    "\n",
    "字典是一种高效的存储结构，其内部使用基于哈希值的算法，用来保证从字典中读取键值对的效率。不过，哈希值算法要求字典的键必须是一种不可变类型。使用可变类型作为键时，Python会抛出异常，例如："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "0496f6ba",
   "metadata": {},
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "unhashable type: 'list'",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[0;32mIn [14]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0m a[[\u001b[38;5;241m1\u001b[39m, \u001b[38;5;241m2\u001b[39m]] \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m1\u001b[39m\n",
      "\u001b[0;31mTypeError\u001b[0m: unhashable type: 'list'"
     ]
    }
   ],
   "source": [
    "a[[1, 2]] = 1"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3cbc00a0",
   "metadata": {},
   "source": [
    "## 适合做键的类型\n",
    "\n",
    "在不可变类型中，整数和字符串是字典中最常用的类型；而浮点数通常不推荐用来做键，原因如下："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "d86a9624",
   "metadata": {},
   "outputs": [],
   "source": [
    "data = {}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "469d4b1d",
   "metadata": {},
   "outputs": [],
   "source": [
    "data[1.1 + 2.2] = 6.6"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "9c9079dd",
   "metadata": {},
   "outputs": [
    {
     "ename": "KeyError",
     "evalue": "3.3",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mKeyError\u001b[0m                                  Traceback (most recent call last)",
      "Input \u001b[0;32mIn [17]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mdata\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m3.3\u001b[39;49m\u001b[43m]\u001b[49m\n",
      "\u001b[0;31mKeyError\u001b[0m: 3.3"
     ]
    }
   ],
   "source": [
    "data[3.3]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8ab83eb4",
   "metadata": {},
   "source": [
    "这个错误是由浮点数的精度问题所引起的："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "1bfae807",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{3.3000000000000003: 6.6}"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "28b05280",
   "metadata": {},
   "source": [
    "也可以使用元组作为键值，例如，可以用元组做键来表示从第一个城市飞往第二个城市航班数的多少："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "c5d20397",
   "metadata": {},
   "outputs": [],
   "source": [
    "connections = {}\n",
    "connections[('New York', 'Seattle')] = 100\n",
    "connections[('Austin', 'New York')] = 200\n",
    "connections[('New York', 'Austin')] = 400"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b5409597",
   "metadata": {},
   "source": [
    "元组是有序的，因此 ('New York', 'Austin') 和 ('Austin', 'New York') 是两个不同的键："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "544fc507",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "200"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "connections[('Austin', 'New York')]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "ee747523",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "400"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "connections[('New York', 'Austin')]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "871b913c",
   "metadata": {},
   "source": [
    "## 字典方法"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7d398529",
   "metadata": {},
   "source": [
    "用`.get()`方法替代索引处理值不存在的情况："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "a749d17e",
   "metadata": {},
   "outputs": [],
   "source": [
    "a = {}\n",
    "a[\"one\"] = \"this is number 1\"\n",
    "a[\"two\"] = \"this is number 2\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "95a94587",
   "metadata": {},
   "source": [
    "值不存在时，`get`方法返回一个默认值，不指定时，该默认值为`None`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "534f9210",
   "metadata": {},
   "outputs": [],
   "source": [
    "a.get(\"three\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8ca3cb1f",
   "metadata": {},
   "source": [
    "传入默认值："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "53abd7e8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'undefined'"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a.get(\"three\", \"undefined\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2a74a230",
   "metadata": {},
   "source": [
    "存在时，与调用索引相同："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "d65dfb77",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'this is number 1'"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a.get(\"one\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b476906e",
   "metadata": {},
   "source": [
    "与列表一样，del 函数可以用来删除字典中特定的键值对，例如："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "e24308dd",
   "metadata": {},
   "outputs": [],
   "source": [
    "del a[\"one\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a57d5f24",
   "metadata": {},
   "source": [
    "`.update()`方法可以更新键值对："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "952f1b6e",
   "metadata": {},
   "outputs": [],
   "source": [
    "person = {}\n",
    "person['first'] = \"Jmes\"\n",
    "person['last'] = \"Maxwell\"\n",
    "person['born'] = 1831"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "4a1ca7a0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'first': 'Jmes', 'last': 'Maxwell', 'born': 1831}"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "person"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "37ecef83",
   "metadata": {},
   "outputs": [],
   "source": [
    "person_modifications = {'first': 'James', 'middle': 'Clerk'}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "c1c22d10",
   "metadata": {},
   "outputs": [],
   "source": [
    "person.update(person_modifications)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "9ac57688",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'first': 'James', 'last': 'Maxwell', 'born': 1831, 'middle': 'Clerk'}"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "person"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "89c38bae",
   "metadata": {},
   "source": [
    "in查询字典中是否有该键："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "03c85648",
   "metadata": {},
   "outputs": [],
   "source": [
    "barn = {'cows': 1, 'dogs': 5, 'cats': 3}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "d9fdd328",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "'chickens' in barn"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "8ab2a42e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "'cows' in barn"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "72a897b6",
   "metadata": {},
   "source": [
    "`.keys()`，`values()`，`items()`方法分别返回字典的键，值，键值对： "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "0d8f2419",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dict_keys(['cows', 'dogs', 'cats'])"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "barn.keys()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "84102501",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dict_values([1, 5, 3])"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "barn.values()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "8ffa508e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dict_items([('cows', 1), ('dogs', 5), ('cats', 3)])"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "barn.items()"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "58584c4f",
   "metadata": {},
   "source": [
    "`.setdefault()`方法接受两个参数：key和default，如果key在字典中，返回其对应的值，如果不存在，则先用default的值对key进行插入，并返回default。其中default的值可以省略，默认值为None："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "40556cf8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "barn.setdefault(\"chickens\", 4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "a1be97cc",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'cows': 1, 'dogs': 5, 'cats': 3, 'chickens': 4}"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "barn"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "490f2da7",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
